home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 551-575 / disk_572 / crossfade / crossfade.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  11KB  |  364 lines

  1. /* CrossFade : A video crossfade simulator (c) 1990 Dallas J. Hodgson
  2.  
  3.    Usage : CrossFade <ILBM-file1> <ILBM-file2>
  4.  
  5.    CrossFade takes 2 four-color ILBM pictures and smoothly crossfades between
  6.    them, using nothing more than color register manipulation! The effect
  7.    is similar to that used in pro video equipment, and lends itself to
  8.    other applications such as animation, depth-arranging, etc. This idea
  9.    could be extended to more bitplanes for extra colors or higher #'s of
  10.    simultaneously-crossfadable images.
  11.  
  12.    HOW IT WORKS:
  13.  
  14.    CrossFade opens a 4-bitplane screen and loads each 4-color image into 
  15.    two bitplanes apiece. This results in a 16-color image, formed by
  16.    the colors in image 1, (registers 0,1,2,3) image 2 (registers 0,4,8,12)
  17.    and other color registers according to the overlap of bits between
  18.    the two images.
  19.  
  20.    To blank out either image, we just set its color registers to the
  21.    transparent color - almost. Wherever bits in bitplanes [0,1] (image 1)
  22.    and [2,3] (image 2) overlap, other pencolors are formed from the overlap
  23.    set { 5,6,7,9,10,11,13,14 }. These color registers have to be filled with
  24.    redundant copies of the image colors we wish to display to prevent nasty
  25.    XOR-type video effects.
  26.  
  27.    To explain this effect in all of its boolean detail would take up to
  28.    much space. Screen-grab a CrossFaded display and manipulate the colors in
  29.    DPaint - you'll see what I mean.
  30.  
  31.    Click on the window-close gadget in the upper left corner of the
  32.    screen to exit.
  33. */
  34.  
  35. #include <exec/memory.h>
  36. #include <libraries/dos.h>
  37. #include <intuition/screens.h>
  38. #include <intuition/intuition.h>
  39. #include <functions.h>
  40.  
  41. extern struct WBStartup *WBenchMsg;
  42.  
  43. #define TITLE "CrossFade 1.0 : (c) 1990 John Hodgson\n"
  44.  
  45. #define MAXWIDTH  376 /* max non-HIRES width */
  46. #define MAXHEIGHT 242 /* max non-interlaced height */
  47. #define MAXCOLORS 32  /* max # colors supported */
  48.  
  49. #define MakeID(a,b,c,d) ((a)<<24L | (b)<<16L | (c)<<8 | (d))
  50.  
  51. #define ID_FORM MakeID('F','O','R','M')
  52. #define ID_ILBM MakeID('I','L','B','M')
  53. #define ID_BMHD MakeID('B','M','H','D')
  54. #define ID_CAMG MakeID('C','A','M','G')
  55. #define ID_CMAP MakeID('C','M','A','P')
  56. #define ID_BODY MakeID('B','O','D','Y')
  57.  
  58. #define cmpByteRun1 1
  59.  
  60. #define ROUNDODDUP(a) (((a)+1)&(~1L))
  61.  
  62. typedef struct {
  63.   long ckID,ckSize;
  64. } Chunk;
  65.  
  66. typedef struct {
  67.   short w,h,x,y;
  68.   char  nPlanes,masking,compression,pad1;
  69.   short transparentColor;
  70.   char  xAspect, yAspect;
  71.   short pageWidth,pageHeight;
  72. } BitMapHeader;
  73.  
  74. #define SafeRead(a,b,c) if (Read(a,b,c)==-1L) { Close(a); return(NULL); }
  75.  
  76. void *IntuitionBase,*GfxBase;
  77.  
  78. /************************************************************************
  79. *                                                                       *
  80. *    Routine name(s) : ReadILBM()                                       *
  81. *    Author          : D. John Hodgson                                  *
  82. *    Environment     : Aztec "C", default                               *
  83. *                                                                       *
  84. *    ReadILBM attempts to read an IFF file and display it on a freshly  *
  85. *    opened custom screen. Returns a screen pointer if sucessful,       *
  86. *    otherwise NULL.                                                    *
  87. *                                                                       *
  88. *    LIMITATIONS : no masking, CATS/LISTS/PROPS. CAMG chunks supported. *
  89. ************************************************************************/
  90.  
  91. void *ReadILBM(fspec,size,bmhd,colormap,NewScreen)
  92. char *fspec;             /* AmigaDOS filename */
  93. long *size;             /* size of allocated buffer */
  94. BitMapHeader *bmhd;         /* header for us to fill */
  95. unsigned char colormap[MAXCOLORS][3];     /* colormap for us to fill */
  96. struct NewScreen *NewScreen;     /* screen struct for us to fill */
  97. {
  98.   struct Screen *screen;
  99.   struct FileHandle *fp;
  100.   char *sourcebuf;
  101.   short i;
  102.   long id,ViewModes=0;
  103.   char *bufstart;
  104.   Chunk header;
  105.  
  106.   setmem(bmhd,sizeof(*bmhd),0);    /* start w/fresh structure */
  107.  
  108.   if ((fp=Open(fspec,MODE_OLDFILE))==0) return(NULL);
  109.  
  110.   SafeRead(fp,&header,(long)sizeof(header));
  111.   if (header.ckID!=ID_FORM) { Close(fp); return(NULL); }
  112.  
  113.   SafeRead(fp,&id,(long)sizeof(id));
  114.   if (id!=ID_ILBM) { Close(fp); return(NULL); }
  115.  
  116.   for (;;) {
  117.     SafeRead(fp,&header,(long)sizeof(header));
  118.  
  119.     if (header.ckID==ID_BODY) break;
  120.  
  121.     switch(header.ckID) {
  122.       case ID_BMHD: SafeRead(fp,bmhd,(long)sizeof(*bmhd));
  123.                     break;
  124.  
  125.       case ID_CMAP: SafeRead(fp,&colormap[0][0],(long)header.ckSize);
  126.             for (i=0;i<header.ckSize;i++) colormap[0][i]>>=4;
  127.                     break;
  128.  
  129.       case ID_CAMG: SafeRead(fp,&ViewModes,(long)header.ckSize);
  130.                     break;
  131.  
  132.       default:      Seek(fp,ROUNDODDUP(header.ckSize),OFFSET_CURRENT);
  133.     }
  134.   }
  135.  
  136.   /* Read planes into RAM for ease of decompression */
  137.      
  138.   sourcebuf=bufstart=AllocMem((long)header.ckSize,MEMF_PUBLIC);
  139.   if (sourcebuf==0L) puts("Error allocating memory!");
  140.   *size=(long)header.ckSize;
  141.  
  142.   SafeRead(fp,sourcebuf,(long)header.ckSize); Close(fp);
  143.  
  144.   setmem(NewScreen,sizeof(*NewScreen),0); /* start fresh */
  145.  
  146.   NewScreen->LeftEdge=0; NewScreen->TopEdge=0;
  147.   NewScreen->Width=bmhd->w; NewScreen->Height=bmhd->h;
  148.   NewScreen->Depth=bmhd->nPlanes;
  149.  
  150.   /* make some forced assumptions if CAMG chunk unavailable */
  151.  
  152.   if (!(NewScreen->ViewModes=ViewModes)) {
  153.     if (bmhd->w>MAXWIDTH) NewScreen->ViewModes|=HIRES;
  154.     if (bmhd->h>MAXHEIGHT) NewScreen->ViewModes|=LACE;
  155.   }
  156.  
  157.   NewScreen->Type=CUSTOMSCREEN;
  158.   NewScreen->Font=0L;
  159.   NewScreen->Gadgets=0L;
  160.  
  161.   return(bufstart);   
  162. }      
  163.  
  164. Expand(screen,bmhd,sourcebuf,planeoffset) /* Fast line decompress/deinterleave */
  165. struct Screen *screen;
  166. BitMapHeader *bmhd;
  167. register char *sourcebuf;
  168. short planeoffset;
  169. {
  170.   
  171.   register char n,*destbuf; /* in order of preferred allocation */
  172.   register short plane,linelen,rowbytes,i;
  173.  
  174.   linelen=bmhd->w/8;
  175.  
  176.   for (i=0;i<bmhd->h;i++) /* process n lines/screen */
  177.     for (plane=0;plane<bmhd->nPlanes;plane++) { /* process n planes/line */
  178.       destbuf=(char *)(screen->BitMap.Planes[plane+planeoffset])+linelen*i;
  179.  
  180.       if (bmhd->compression==cmpByteRun1) { /* compressed screen? */
  181.         rowbytes=linelen;
  182.  
  183.         while (rowbytes) { /* unpack until 1 scan-line complete */
  184.           n=*sourcebuf++; /* fetch block run marker */
  185.  
  186.           /* uncompressed block? copy n bytes verbatim */
  187.           if (n>=0) {
  188.             movmem(sourcebuf,destbuf,(unsigned int)++n); rowbytes-=n;
  189.             destbuf+=n; sourcebuf+=n;
  190.           }
  191.           else { /* compressed block? expand n duplicate bytes */
  192.             n=-n+1; rowbytes-=n;
  193.             setmem(destbuf,(unsigned int)n,(unsigned int)*sourcebuf++);
  194.             destbuf+=n;
  195.           }
  196.  
  197.         } /* finish unpacking line */
  198.       }
  199.       else { /* uncompressed? just copy */
  200.         movmem(sourcebuf,destbuf,(unsigned int)linelen);
  201.         sourcebuf+=linelen; destbuf+=linelen;
  202.       }
  203.     } /* finish interleaved planes, lines */
  204. }
  205. load_colormap(screen,colormap)
  206. struct Screen *screen;
  207. char colormap[MAXCOLORS][3];
  208. {
  209.   short i,colorcnt=1<<screen->BitMap.Depth;
  210.  
  211.   /* Sure, LoadRGB is faster, but uses UWORDS for its colors! */
  212.  
  213.   for (i=0;i<colorcnt;i++) {
  214.     SetRGB4(&screen->ViewPort,(long)i,
  215.        (long)colormap[i][0],(long)colormap[i][1],
  216.           (long)colormap[i][2]);
  217.   }
  218. }
  219.  
  220. create_image1x4_colors(srcmap,dstmap)
  221. char srcmap[MAXCOLORS][3],dstmap[MAXCOLORS][3];
  222. {
  223.   short i,j;
  224.  
  225.   /* create image 1's color palette. Duplicates image 1 colors
  226.      into the xx11 registers. */
  227.  
  228.   for (i=0;i<16;i++) 
  229.     for (j=0;j<3;j++)
  230.       dstmap[i][j]=srcmap[i%4][j];
  231. }
  232.  
  233. create_image2x4_colors(srcmap,dstmap)
  234. char srcmap[MAXCOLORS][3],dstmap[MAXCOLORS][3];
  235. {
  236.   short i,j;
  237.  
  238.   /* create image 2's color palette */
  239.  
  240.   for (i=0;i<=4;i++)
  241.     for (j=0;j<3;j++)
  242.       dstmap[i*4][j]=srcmap[i][j];
  243.  
  244.   /* Duplicate the image2 colors into the 11xx registers */
  245.  
  246.   for (i=0;i<16;i++) {
  247.     if (i%4) {
  248.        for (j=0;j<3;j++) 
  249.          dstmap[i][j]=srcmap[(i & 0x0c)/4][j];
  250.     }
  251.   }
  252.  
  253. FadeAtoB(screen,srcmap,dstmap)
  254. struct Screen *screen;
  255. char srcmap[MAXCOLORS][3],dstmap[MAXCOLORS][3];
  256. {
  257.   short i,j,flag,colorcnt=1<<screen->BitMap.Depth;
  258.  
  259.   do {
  260.     flag=0;
  261.  
  262.     for (i=0;i<colorcnt;i++) {
  263.       for (j=0;j<3;j++) {
  264.         if (srcmap[i][j]!=dstmap[i][j]) {
  265.           srcmap[i][j]+=SIGN(dstmap[i][j]-srcmap[i][j]);
  266.           flag=1;
  267.         }
  268.       }
  269.     }
  270.     load_colormap(screen,srcmap);
  271.     Delay(5);
  272.   }
  273.   while(flag);
  274. }     
  275.  
  276. main(argc,argv)
  277. int argc;
  278. char *argv[];
  279. {
  280.   struct Screen *screen=0;
  281.   struct Window *window=0;
  282.   struct NewWindow nw;
  283.   struct NewScreen NewScreen1,NewScreen2;
  284.   BitMapHeader bmhd1,bmhd2;
  285.   char *buf1=0,*buf2=0;
  286.   long size1,size2;
  287.   short i;
  288.  
  289.   char colormap1[MAXCOLORS][3],colormap2[MAXCOLORS][3],
  290.        colormapA[MAXCOLORS][3],colormapB[MAXCOLORS][3];
  291.  
  292.   GfxBase=OpenLibrary("graphics.library",0L);
  293.   IntuitionBase=OpenLibrary("intuition.library",0L);
  294.  
  295.   setmem(&nw,sizeof(nw),0); /* start w/fresh structure */
  296.  
  297.   puts(TITLE);    /* CLI title */
  298.  
  299.   if (!(buf1=ReadILBM(argv[1],&size1,&bmhd1,colormap1,&NewScreen1))) {
  300.     printf("Error reading IFF file %s.\n",argv[1]);
  301.     goto cleanup;
  302.   }
  303.  
  304.   if (NewScreen1.Depth!=2) {
  305.     printf("ILBM file %s must be 2 bitplanes. %d found.\n",argv[1],NewScreen1.Depth);
  306.     goto cleanup;
  307.   }
  308.     
  309.   if (!(buf2=ReadILBM(argv[2],&size2,&bmhd2,colormap2,&NewScreen2))) {
  310.     printf("Error reading IFF file %s.\n",argv[2]);
  311.     goto cleanup;
  312.   }
  313.  
  314.   if (NewScreen2.Depth!=2) {
  315.     printf("ILBM file %s must be 2 bitplanes. %d found.\n",argv[2],NewScreen2.Depth);
  316.     goto cleanup;
  317.   }
  318.  
  319.   NewScreen1.Depth+=NewScreen2.Depth;
  320.  
  321.   create_image1x4_colors(colormap1,colormapA);
  322.   create_image2x4_colors(colormap2,colormapB);
  323.  
  324.   if (!(screen=OpenScreen(&NewScreen1))) {
  325.     puts("Couldn't open screen!");
  326.     goto cleanup;
  327.   }
  328.     
  329.   load_colormap(screen,colormapA);
  330.  
  331.   nw.IDCMPFlags=CLOSEWINDOW;
  332.   nw.Flags=SIMPLE_REFRESH|BORDERLESS|WINDOWCLOSE;
  333.   nw.Screen=screen;
  334.   nw.Type=CUSTOMSCREEN;
  335.   nw.Height=bmhd1.h; nw.Width=bmhd1.w;
  336.  
  337.   if (!(window=OpenWindow(&nw))) { CloseScreen(screen); exit(100); }
  338.  
  339.   Expand(screen,&bmhd1,buf1,0); /* fill bitplanes 0-1, image 1 */
  340.   Expand(screen,&bmhd2,buf2,2); /* fill bitplanes 1-2, image 2 */
  341.  
  342.   Delay(100);
  343.  
  344.   while (!GetMsg(window->UserPort)) { /* until CloseWindow */
  345.     FadeAtoB(screen,colormapA,colormapB);
  346.     create_image1x4_colors(colormap1,colormapB);
  347.     create_image2x4_colors(colormap2,colormapA);
  348.     Delay(20);
  349.     FadeAtoB(screen,colormapA,colormapB);
  350.     create_image1x4_colors(colormap1,colormapA);
  351.     create_image2x4_colors(colormap2,colormapB);
  352.   }
  353.  
  354. cleanup:
  355.   if (buf1) FreeMem(buf1,size1);   /* free compressed buffer */
  356.   if (buf2) FreeMem(buf2,size2);   /* free compressed buffer */
  357.   if (window) CloseWindow(window); /* Intuition will ReplyMsg() for us */
  358.   if (screen) CloseScreen(screen);
  359.  
  360.   CloseLibrary(IntuitionBase);
  361.   CloseLibrary(GfxBase);
  362. }
  363.